//
//  ResultsViewController.swift
//  Automobile
//
//  Created by erkebulan elzhan on 7/21/20.
//  Copyright © 2020 erkebulan elzhan. All rights reserved.
//

import UIKit
import SnapKit


protocol ResultsVCDelegate {
    func goBack (data: CarFilter, type: MarkaModelMode)
}

final class ResultsViewController: UIViewController, Alertable {
    
    // MARK: - Outlets
    
    private lazy var tableView: UITableView = {
        let tableView = UITableView()
        tableView.showsVerticalScrollIndicator = false
        tableView.backgroundColor = UIColor(red: 244/255, green: 246/255, blue: 250/255, alpha: 1)
        tableView.separatorStyle = .none
        let view = UIView()
        view.frame = CGRect(x: 0, y: 0, width: tableView.frame.width, height: 30.0)
        view.backgroundColor = UIColor(red: 244/255, green: 246/255, blue: 250/255, alpha: 1)
        tableView.tableHeaderView = view
        tableView.register(SegmentedCell.self, forCellReuseIdentifier: "SegmentedCell")
        tableView.register(ParametersCell.self, forCellReuseIdentifier: "ParametersCell")
        tableView.register(PostCell.self, forCellReuseIdentifier: "PostCell")
        tableView.register(ButtonsCell.self, forCellReuseIdentifier: "ButtonsCell")
        tableView.delegate = self
        tableView.dataSource = self
        tableView.addSubview(refreshControl)
        return tableView
    }()
    
    private lazy var sortView: SortView = {
        let sortView = SortView()
        sortView.parentVC = self
        return sortView
    }()
    
    private lazy var emptyView: EmptyView = {
        let emptyView = EmptyView()
        emptyView.frame = CGRect(x: 0, y: 0,
                                 width: tableView.frame.width, height: 200)
        return emptyView
    }()
    
    private lazy var settingsBtn: SettingsBtn = {
        let btn = SettingsBtn()
        btn.applyBlueStyle()
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(settingsBtnClick(sender:)))
        btn.addGestureRecognizer(tapGesture)
        return btn
    }()
    
    private lazy var refreshControl: RefreshView = {
        let refControl = RefreshView()
        refControl.addTarget(self, action: #selector(doRefresh), for: .valueChanged)
        return refControl
    }()
    
    private lazy var spinnerView = SpinnerView()
    
    // MARK: - Props
    
    private lazy var viewModel: ResultsViewModel = {
        let vm = ResultsViewModel()
        vm.delegate = self
        return vm
    }()
    
    // MARK: - Init
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.addView()
        viewModel.initFilter()
        self.setUpNavBar()
    }
}


// MARK: - Public Methods

extension ResultsViewController {
    public func addFilter (filter: Filter) {
        if filter.filterCar.carParameters != nil {
            self.viewModel.updateMarkModel(carFilter: filter.filterCar.carParameters!)
        }
        viewModel.filter = filter
    }
    
    public func setSort (sortId: Int) {
        viewModel.filter.sortBy = sortId
    }
    
    public func putMarkData (carData: CarData) {
        var filter = viewModel.filter!
        
        filter.filterCar.carParameters = CarFilter(marka: carData.marka, models: carData.models ?? [])
        filter.filterGeneral.region = carData.currentRegion
        filter.carDetailedType = carData.vehicleType
        filter.mode = carData.mode
        viewModel.filter = filter
    }
}


// MARK: - Private Methods

extension ResultsViewController {
    @objc private func selectSortMethod (sender: Any) {
        self.showSortView()
    }
    
    @objc private func goBack (sender: UIBarButtonItem) {
        self.navigationController?.popViewController(animated: true)
    }
    
    @objc private func settingsBtnClick (sender: UIPanGestureRecognizer) {
        self.openFilters()
    }
    
    @objc private func doRefresh () {
        refreshControl.endRefreshing()
        viewModel.loadPosts()
    }
    
    private func selectMark (filter: Filter) {
        let vc = MarksViewController()
        let carData = CarData(marka: filter.filterCar.carParameters?.marka, type: .legkovye, vehicleType: filter.carDetailedType, currentRegion: filter.filterGeneral.region)
        
        vc.setProps(carData: carData, resultDelegate: self)
        self.navigationController?.pushViewController(vc, animated: true)
    }
    
    private func selectModels (filter: Filter) {
        let vc = ModelsViewController()
        let carData = CarData(marka: filter.filterCar.carParameters?.marka, type: .legkovye, vehicleType: filter.carDetailedType, currentRegion: filter.filterGeneral.region)
        
        vc.setProps(carData: carData, resultDelegate: self)
        self.navigationController?.pushViewController(vc, animated: true)
    }
    
    private func selectGeneration (filter: Filter) {
        let vc = GenerationViewController()
        var _models:[Model] = []
        
        for (_, model) in filter.filterCar.carParameters!.models.enumerated() {
            var _model = model
            _model.generation = nil
            _models.append(_model)
        }
        
        vc.models = _models
        vc.carData = CarData(marka: filter.filterCar.carParameters?.marka)
        vc.resultsVC = self
        self.navigationController?.pushViewController(vc, animated: true)
    }
}


// MARK: - Cell Actions

extension ResultsViewController {
    @objc private func onLikeClick (sender: UIButton) {
        let otherCellsCount = viewModel.items.count - viewModel.posts.count
        let index = sender.tag - otherCellsCount
        viewModel.updateFavorite(index: index)
    }
}


// MARK: - UI Table View Configuration

extension ResultsViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if viewModel.items[indexPath.row] is PostCellConfigurator {
            let carInfoVC = MainViewController()
            carInfoVC.setProps(post: (viewModel.items[indexPath.row] as! PostCellConfigurator).item?.post)
            self.navigationController?.pushViewController(carInfoVC, animated: true)
        }
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return viewModel.items.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let item = viewModel.items[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: type(of: item).reuseId)!
        (cell as! OptionCellProtocol).delegate = self
        item.configure(cell: cell, index: indexPath.row)
        
        (cell as? PostCell)?.likeButton.tag = indexPath.row
        (cell as? PostCell)?.likeButton.addTarget(self, action: #selector(onLikeClick(sender:)), for: .touchUpInside)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
    
    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        
        if viewModel.items.filter({ $0 is PostCellConfigurator }).count == 0 {
            let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 200))
            view.addSubview(emptyView)
            return emptyView
        } else {
            let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 48))
            view.addSubview(settingsBtn)
            settingsBtn.snp.makeConstraints { (make) in
                make.center.equalToSuperview()
            }
            return view
        }
    }
    
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return viewModel.items.filter { $0 is PostCellConfigurator }.count == 0 ? 200 : 60
    }
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        let offsetY = scrollView.contentOffset.y
        let contentHeight = scrollView.contentSize.height
        
        if offsetY > contentHeight - scrollView.frame.size.height {
            if viewModel.nextPage != nil {
                viewModel.loadPosts(paginate: true)
            }
        }
    }
}


// MARK: Cell Actions

extension ResultsViewController: OptionCellActionProtocol, ResultsVCDelegate {

    // Открыть параметры
    func openFilters() {
        let filtersVC = FilterViewController()
        filtersVC.filter = viewModel.filter
        filtersVC.resultVC = self
        self.navigationController?.pushViewController(filtersVC, animated: true)
    }
    
    // Очистить параметр
    func clearParameterValue(value: String?, placeholder: String, index: Int, itemIndex: Int) {
        self.removeEmptyView(ind: index, itemIndex: itemIndex)
    }
    
    // Нажал на один параметр
    func selectMarkaModel(index: Int, item: ParametersViewModel?) {
        
        let filter = viewModel.filter
        
        if (item?.type == "marka") {
            self.selectMark(filter: filter!)
        } else if item?.type == "model" {
            self.selectModels(filter: filter!)
        } else {
            self.selectGeneration(filter: filter!)
        }
    }
        
    // (Все, Новые, С пробегом обновили)
    
    func changeCarType(newValue: String, item: Segmented) {
        viewModel.filter.filterGeneral.transportFeature = newValue
    }
    
    // MARK: ResultsDelegate:
    
    func goBack(data: CarFilter, type: MarkaModelMode) {
        self.viewModel.updateMarkModel(carFilter: data)
        viewModel.filter.filterCar.carParameters = data
    }
}

// MARK: - UI

extension ResultsViewController {
    
    private func addView () {
        view.addSubview(tableView)
        view.addSubview(spinnerView)
        
        tableView.snp.makeConstraints { (make) in
            make.bottom.top.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
        }
        
        spinnerView.snp.makeConstraints { (make) in
            make.center.equalToSuperview()
        }
    }
    
    // Parameters Cell
    private func removeEmptyView (ind: Int, itemIndex: Int) {
        viewModel.filter.filterCar.carParameters = viewModel.clearParameter(cellIndex: ind, parameterIndex: itemIndex)
        tableView.reloadRows(at: [IndexPath(row: ind, section: 0)], with: .top)
    }
    
    private func showSortView () {
        self.view.addSubview(sortView)
        sortView.snp.makeConstraints { (make) in
            make.bottom.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
            make.height.equalToSuperview().dividedBy(1.5)
        }
    }
    
    func hideShowView () {
        sortView.removeFromSuperview()
    }

    private func setUpNavBar() {
        let backIcon = UIImage(named: "cancel")
        let backButton = UIBarButtonItem(image: backIcon, style: .plain, target: self, action: #selector(goBack(sender:)))
        backButton.tintColor = .greyColor
        
        let sortBtn = UIBarButtonItem(image: UIImage(named: "sort"), style: .plain, target: self, action: #selector(selectSortMethod(sender:)))
        
        self.navigationItem.leftBarButtonItem = backButton
        self.navigationItem.rightBarButtonItem = sortBtn
        self.navigationItem.largeTitleDisplayMode = .never
        self.navigationController?.navigationBar.defaultNavBar()
        self.navigationController?.navigationBar.backgroundColor = .white
        self.navigationItem.setTitle(title: "Сначало новые", subtitle: "Найдено " + String((viewModel.posts ?? []).count))
        self.view.backgroundColor = .white
    }
}


extension ResultsViewController: ViewModelProtocol {
    
    func updateSpinner(showSpinner: Bool) {
        showSpinner ? spinnerView.startAnimating() : spinnerView.stopAnimating()
        view.isUserInteractionEnabled = !showSpinner
    }
    
    func didHappenError(error: RequestError) {
        self.alertError(error: error)
    }
    
    func updatePosts() {
        self.tableView.reloadData()
        self.navigationItem.setTitle(title: "Сначало новые", subtitle: "Найдено " + String((viewModel.posts ?? []).count))
    }
    
    // MARK: Never Executes
    
    func updateCities(cities: [City]?) {}
}
